#
#       Author: Alexandros Sigalas
#
#      This program is free software; you can redistribute it and/or modify
#      it under the terms of the GNU General Public License as published by
#      the Free Software Foundation; either version 2 of the License, or
#      (at your option) any later version.
#      
#      This program is distributed in the hope that it will be useful,
#      but WITHOUT ANY WARRANTY; without even the implied warranty of
#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#      GNU General Public License for more details.
#      
#      You should have received a copy of the GNU General Public License
#      along with this program; if not, write to the Free Software
#      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#      MA 02110-1301, USA.

cdef extern from "math.h":
    double fabs(double d)nogil
    double sqrtf(double d)nogil

cdef extern from "stdlib.h":
    ctypedef unsigned long size_t
    void free(void *ptr) nogil
    void *malloc(size_t size) nogil
    void *realloc(void *ptr, size_t size) nogil
    void *calloc(size_t nelem, size_t elsize) nogil

cdef extern from "globals.h":
    ctypedef unsigned int uint
    int IN, ON, ONIN, OUT, ONOUT, CR, ONCR, FR, ONFR, BK, ONBK
    enum axis_pair:
        XY, XZ, YZ   

cdef extern from "mathutils.h":
    ctypedef double matrix[4][4]
    struct Vec:
        double x,y,z
    ctypedef Vec vec
       
    void v_mul_mx (vec *dest, vec *v,  matrix mx) nogil
    void v_add(vec *dest, vec *v0, vec *v1) nogil
    void v_sub(vec *dest, vec *v0, vec *v1) nogil
    void v_scale (vec *dest, vec *v, double s) nogil
    void v_cross (vec *dest, vec *v0,  vec *v1) nogil
    double v_dot (vec *v0, vec *v1) nogil
    double v_perp (vec *v0,  vec *v1, axis_pair ax) nogil
    int same_2d(vec *v0,  vec *v1, axis_pair ax) nogil
    int same_3d(vec *v0,  vec *v1) nogil
    
    double v_length (vec * v) nogil
    void v_normal (vec *dest, vec * v) nogil
    void v_zero (vec * v) nogil

    void v_copy(vec *dest, vec *src) nogil
    void v_swp_xy (vec *dest, vec *src) nogil
    void v_swp_yz (vec *dest, vec *src) nogil
    void v_swp_xz (vec *dest, vec *src) nogil
    void v_flat_x (vec *dest, vec *src) nogil
    void v_flat_y (vec *dest, vec *src) nogil
    void v_flat_z (vec *dest, vec *src) nogil
    void v_flat_persp (vec *dest, vec *src) nogil
    
    void mx_copy(matrix dst_mx,  matrix src_mx)nogil
    void mx_identity "mx_set_identity"(matrix mx)nogil
    void mx_rotation "mx_set_rotation" (matrix mx,  float rot_x,  float rot_y,  float rot_z)nogil
    void mx_translation "mx_set_translation" (matrix mx,  double dx,  double dy,  double dz)nogil
    void mx_transpose "mx_transpose" (matrix mx) nogil
    int mx_invert "mx_invert" (matrix mx) nogil
    void mx_mul_mx "mx_mul" (matrix mx,  matrix mx_a,  matrix mx_b) nogil
    void mx_mul_scalar "mx_mul_scalar" (matrix dst, matrix mx,  double s) nogil

    int rel_point_plane( vec *point,  vec *pp,  vec *pn) nogil
    int line_intersect_plane( vec *v0,  vec *v1,  vec *pp,  vec *pn, vec *isx) nogil
    int point_in_segment_2d(vec *p,  vec *p0,  vec *p1, axis_pair ax) nogil
    void midpoint(vec * dest, vec *v0, vec * v1) nogil
    double dist(vec * v0,  vec * v1) nogil

cdef extern from "bounds.h":
    struct Bounds:
        vec min, max

    ctypedef Bounds *bounds

    void check_bounds(bounds b, vec *point)nogil
    int disjoint_2d(bounds b0, bounds b1, axis_pair ax)nogil
    int disjoint_3d(bounds b0, bounds b1)nogil
    int point_in_bounds_2d (bounds b0, vec *p, axis_pair ax)nogil
    int point_in_bounds (bounds b, vec *p)nogil

cdef extern from "material.h":
    struct ColorF:
        float r, g, b

    ctypedef ColorF col

    struct Material:
        char name[64]
        ColorF fill_color
        ColorF line_color
        float alpha
        float lineweight
        Material *section
        Material *hidden
        
    ctypedef Material *material
    material ma_init(char* name)
    void ma_rename(material mat, char* name)

cdef extern from "polygon.h":
    enum PL_Order:
        CW=0
        CCW

    enum PL_Attr:
        HIDDEN, HOLE, SECTION, BACKF, CLIPPED

    struct PL_Vertex:
        vec co
        int flags

    struct PL_Props:
        unsigned int coplanar_id
        unsigned int crease_id
        float shade_f

    struct Polygon
    struct PL_List:
        Polygon **polys
        unsigned int size, last

    struct Polygon:
        PL_Vertex *points
        uint size, last
        int flag
        int attr
        Bounds bb
        PL_List *holes
        PL_Props props
        Material *mat

    ctypedef Polygon *polygon

    polygon pl_init (uint count) nogil
    polygon pl_copy (polygon pl, void (*cpy)(vec *dest, vec *src), int do_holes) nogil
    int pl_add_hole (polygon pl, polygon hole) nogil

    void pl_kill (polygon *pl) nogil

    PL_Vertex* pl_append (polygon *pl, vec *co, int flags) nogil
    PL_Vertex* pl_append_point (polygon *pl, vec *p) nogil
    PL_Vertex* pl_append_vertex (polygon *pl, PL_Vertex *pt) nogil

    PL_Vertex* pl_insert_point (polygon pl, vec *p, uint pos) nogil
    PL_Vertex* pl_insert_vertex (polygon pl, PL_Vertex *p, uint pos) nogil

    void pl_extend_verts (polygon pl, PL_Vertex *points, uint count) nogil
    void pl_extend_points (polygon pl, vec *points, uint count) nogil
    void pl_reverse (polygon pl) nogil
    void pl_prj_to_plane (polygon pl,  vec *pp,  vec *pn,  vec *direction) nogil
    
    void pl_normal (polygon pl, vec *normal) nogil
    
    double pl_area_3d(polygon pl, int do_holes) nogil
    double pl_area_2d(polygon pl, axis_pair ax, int do_holes) nogil
    
    PL_Order pl_order(polygon pl) nogil
    PL_Order pl_order_2d(polygon pl) nogil

    int pl_rel_point_2d (polygon pl, vec *p, axis_pair ax, int do_holes) nogil
    int pl_rel_plane (polygon pl,  vec *pp,  vec *pn, int *rmap) nogil
    int pl_self_intersects (polygon pl, axis_pair ax) nogil

    unsigned int pl_rm_doubles_2d (polygon pl, axis_pair ax) nogil
    unsigned int pl_rm_doubles_3d (polygon pl) nogil
    unsigned int pl_simplify_3d (polygon pl) nogil
    unsigned int pl_simplify_2d (polygon pl, axis_pair ax) nogil

    void pl_split_by_plane (polygon pl,\
                            vec *pp, vec *pn,\
                            PL_List **fparts, PL_List **bparts,\
                            int do_holes) nogil


    ctypedef PL_List *polylist

    polylist pll_init (unsigned int count) nogil
    void pll_kill (polylist *pll) nogil
    void pll_killall (polylist *pll) nogil
    
    void pll_append(polylist *pll, polygon pl)nogil
    polygon pll_pop (polylist pll)nogil
    
    polylist pll_copy (polylist pll, void (*copy_method)(vec *dest, vec *src))nogil
    
    int pll_remove_pl (polylist pll, polygon pl) nogil
    polygon pll_rem_poly_idx (polylist pll, unsigned int idx) nogil
    unsigned int pll_count_points (polylist pll) nogil
    void pll_extend (polylist *pll, polygon *polys, unsigned int count) nogil
    polygon pll_replace (polylist pll, unsigned int i, polygon pl) nogil
    void pll_replace_pl (polylist pll, unsigned int i, polygon pl) nogil

    void pll_sort_by_area (polylist pll) nogil

cdef extern from "boolean.h":
    enum itype:
        NOTYPE= 0, EN, EX, ENEX, EXEN, INVALID

    enum BL_Set:
        A=0, B
        
    enum BL_Op:
        UNION, SUBTRACT_A_B, SUBTRACT_B_A, INTERSECT

    struct BL_Node:
        pass
    
    struct BL_Poly:
        polygon pl
        int hole
        int has_entry
        BL_Set set
        int rel

    struct BL_Graph:
        BL_Node* nodes
        unsigned int last, size, inum
        BL_Poly* polys
        BL_Poly* pl_a
        BL_Poly* pl_b
        unsigned int pl_num

    BL_Graph* bl_build_graph(polygon pl_a, polygon pl_b)nogil
    void bl_kill_graph(BL_Graph *g)nogil
    polylist bl_operation(BL_Graph *g, BL_Op op)nogil


cdef extern from "mesh.h":
    enum EdgeFlags:
        COPLANAR= 1, CREASE= 2, PROJECT=4

    struct M_Vert:
        vec co
        int flags

    ctypedef M_Vert *mvert

    struct M_Face
    
    struct FaceList:
        M_Face **faces
        uint last
        uint size
    
    ctypedef FaceList *facelist
    
    struct M_Edge:
        int flags
        mvert v0
        mvert v1
        facelist users
    
    ctypedef M_Edge *medge

    struct M_Face:
        mvert verts[3]
        medge edges[3]
        material mat
        int flags
    
    ctypedef M_Face *mface

    struct Mesh:
        mface faces
        medge edges
        mvert verts
        material mat
        uint size_v, size_e, size_f
        uint last_v, last_e, last_f
        Bounds bb
        
    ctypedef Mesh *mesh

    mesh me_init () nogil
    void me_kill (mesh *me_pt) nogil

    mface me_add_face (mesh me, uint vx0, uint vx1, uint vx2) nogil
    int me_del_face (mesh me, uint idx) nogil
    int me_kill_face (mesh me, uint idx) nogil

    mvert me_add_vert (mesh me, vec * co) nogil
    int me_del_vert (mesh me, uint idx) nogil

    medge me_find_edge (mesh me, uint idx0, uint idx1) nogil
    medge me_add_edge (mesh me, uint idx, uint vx1) nogil
    int me_del_edge (mesh me, uint idx)nogil
    int me_kill_edge (mesh me, uint idx)nogil

    #uint me_edge_faces(mesh me, medge edge, uint *users)nogil
    uint me_vertex_edges (mesh me, mvert vx, uint *users) nogil
    void me_mark_creases (mesh me, float angle)nogil

    void face_normal "mf_normal" (mface f, vec *no) nogil
    facelist face_neighbours "mf_adjascent_faces" (mface f)nogil

    #facelist fl_init(uint count)nogil
    #void fl_append(facelist *fl_pt, mface face)nogil
    #void fl_extend(facelist *fl_pt, mface *faces, uint count)nogil
    #mface fl_pop(facelist fl)nogil
    #mface fl_remove(facelist fl, uint idx)nogil
    #int fl_remove_f(facelist fl, mface face)nogil

    void fl_kill (facelist *fl_pt) nogil
    void fl_killall (facelist *fl_pt) nogil
    
    PL_List * me_to_polys(mesh me, double threshold, uint *coplanar_id) nogil


